#include "ParticleEmitter.h"
#include "SGD Wrappers\SGD_Math.h"
CParticleEmitter::CParticleEmitter()
{
	srand(unsigned int(time(0)));
	m_pD3D = CSGD_Direct3D::GetInstance();
	m_pTM = CSGD_TextureManager::GetInstance();
	// call new on m_nMaxParticles of particles here
	temppart = new CParticle();
}
CParticleEmitter::~CParticleEmitter()
{
	// call delete on m_nMaxParticles of particles here
	if(temppart != nullptr)
	{
		delete temppart;
	}
	if(m_nImageID != NULL)
	{
		m_nImageID = NULL;
	}
}
void CParticleEmitter::Render()
{
	auto iter = m_lLive.begin();
	while(iter != m_lLive.end())
	{
		m_pD3D->GetDirect3DDevice()->GetRenderState(D3DRS_SRCBLEND,&m_ePrevSourceBlend);
		m_pD3D->GetDirect3DDevice()->GetRenderState(D3DRS_DESTBLEND,&m_ePrevDestBlend);
		m_pD3D->GetDirect3DDevice()->SetRenderState(D3DRS_SRCBLEND, (*iter)->GetSourceBlend());
		m_pD3D->GetDirect3DDevice()->SetRenderState(D3DRS_DESTBLEND, (*iter)->GetDestBlend());
		m_pTM->Draw((*iter)->GetImageID(),(*iter)->GetPosX(),(*iter)->GetPosY(),
			(*iter)->GetScaleXCurr(),(*iter)->GetScaleYCurr(),0,m_fWidth*0.5f,
			m_fHeight*0.5f, (*iter)->GetRotation(),
			D3DCOLOR_RGBA((*iter)->GetColorRCurr(),(*iter)->GetColorGCurr(),(*iter)->GetColorBCurr(),
			(*iter)->GetColorACurr()));
		iter++;
	}
	m_pD3D->GetDirect3DDevice()->SetRenderState(D3DRS_SRCBLEND, m_ePrevSourceBlend);
	m_pD3D->GetDirect3DDevice()->SetRenderState(D3DRS_DESTBLEND, m_ePrevDestBlend);
	m_pD3D->GetSprite()->Flush();
}
void CParticleEmitter::Update(float fElapsedTime)
{
	if(m_lLive.begin() != m_lLive.end())
	{
		auto iter = m_lLive.begin();
		while(iter != m_lLive.end())
		{
			if((*iter)->GetLife() > (*iter)->GetCurrLife())
			{
				float templife = (*iter)->GetCurrLife()/(*iter)->GetLife();
				float clrASt = (float)(*iter)->GetColorAStart();
				float clrAEnd = (float)(*iter)->GetColorAEnd();
				float lerpdClr = Lerp(clrASt, clrAEnd, templife);
				(*iter)->SetColorACurr((int)lerpdClr);
				(*iter)->SetColorRCurr((int)Lerp((float)(*iter)->GetColorRStart(),(float)(*iter)->GetColorREnd(),templife));
				(*iter)->SetColorGCurr((int)Lerp((float)(*iter)->GetColorGStart(),(float)(*iter)->GetColorGEnd(),templife));
				(*iter)->SetColorBCurr((int)Lerp((float)(*iter)->GetColorBStart(),(float)(*iter)->GetColorBEnd(),templife));
				(*iter)->SetVelocityXCurr((int)Lerp((float)(*iter)->GetVelocityXStart(),(float)(*iter)->GetVelocityXEnd(),templife));
				(*iter)->SetVelocityYCurr((int)Lerp((float)(*iter)->GetVelocityYStart(),(float)(*iter)->GetVelocityYEnd(),templife));
				(*iter)->SetScaleXCurr(Lerp((*iter)->GetScaleXStart(),(*iter)->GetScaleXEnd(),templife));
				(*iter)->SetScaleYCurr(Lerp((*iter)->GetScaleYStart(),(*iter)->GetScaleYEnd(),templife));
				(*iter)->SetCurrLife((*iter)->GetCurrLife()+fElapsedTime);
				if((*iter)->GetVelocityXCurr() >= 0 && (*iter)->GetPosX() < m_rSpawnRect.right
					&& (*iter)->GetPosX() > m_rSpawnRect.left && (*iter)->GetPosY() < m_rSpawnRect.bottom
					&& (*iter)->GetPosY() > m_rSpawnRect.top)
				{
					if(fElapsedTime < 1.0f)
					{
						(*iter)->SetPosX((*iter)->GetPosX()+(*iter)->GetVelocityXCurr()/2);
						(*iter)->SetPosY((*iter)->GetPosY()+(*iter)->GetVelocityYCurr()/2);
					}
					else
					{
						(*iter)->SetPosX((*iter)->GetPosX()+(*iter)->GetVelocityXCurr()*(int)fElapsedTime);
						(*iter)->SetPosY((*iter)->GetPosY()+(*iter)->GetVelocityYCurr()*(int)fElapsedTime);
					}
				}
				else if((*iter)->GetVelocityXCurr() < 0 && (*iter)->GetPosX() < m_rSpawnRect.right
					&& (*iter)->GetPosX() > m_rSpawnRect.left && (*iter)->GetPosY() < m_rSpawnRect.bottom
					&& (*iter)->GetPosY() > m_rSpawnRect.top)
				{
					(*iter)->SetPosX((*iter)->GetPosX()-(*iter)->GetVelocityXCurr()*(int)fElapsedTime);
					(*iter)->SetPosY((*iter)->GetPosY()-(*iter)->GetVelocityYCurr()*(int)fElapsedTime);
				}
				iter++;
			}
			else
			{
				m_lDead.push_back((*iter));
				m_lLive.remove((*iter));
				iter = m_lLive.begin();
			}
		}
	}
	else
	{

	}
}
void CParticleEmitter::SpawnParticles(char const*const thestring)
{
	Load(thestring);
	for(int i = 0; i < m_nMaxParticle; i++)
	{
		int SRtop = m_rSpawnRect.top;
		int SRleft = m_rSpawnRect.left;
		int SRright = m_rSpawnRect.right;
		int SRbottom = m_rSpawnRect.bottom;
		temppart->SetPosX(rand() % (SRright - SRleft) + SRleft);
		temppart->SetPosY(rand() % (SRbottom - SRtop) + SRtop);
		temppart->SetRotation(D3DXToRadian(m_fRotationStart));
		temppart->SetLife(rand() % ((int)m_fLifeMax - (int)m_fLifeMin) + (int)(m_fLifeMin));
		//setting up velocity
		temppart->SetVelocityXCurr(rand() % (int)(m_fVelocityXMax - m_fVelocityXMin) + m_fVelocityXMin);
		temppart->SetVelocityYCurr(rand() % (int)(m_fVelocityYMax - m_fVelocityYMin) + m_fVelocityYMin);
		temppart->SetVelocityXStart(m_fVelocityXStart);
		temppart->SetVelocityYStart(m_fVelocityYStart);
		temppart->SetVelocityXEnd(m_fVelocityXEnd);
		temppart->SetVelocityYEnd(m_fVelocityYEnd);
		//setting up color
		temppart->SetColorACurr(m_nColorAStart);
		temppart->SetColorRCurr(m_nColorRStart);
		temppart->SetColorBCurr(m_nColorBStart);
		temppart->SetColorGCurr(m_nColorGStart);
		temppart->SetColorAStart(m_nColorAStart);
		temppart->SetColorRStart(m_nColorRStart);
		temppart->SetColorBStart(m_nColorBStart);
		temppart->SetColorGStart(m_nColorGStart);
		temppart->SetColorAEnd(m_nColorAEnd);
		temppart->SetColorREnd(m_nColorREnd);
		temppart->SetColorBEnd(m_nColorBEnd);
		temppart->SetColorGEnd(m_nColorGEnd);
		//setting up scale
		temppart->SetScaleXCurr(m_fScaleXStart);
		temppart->SetScaleYCurr(m_fScaleYStart);
		temppart->SetScaleXStart(m_fScaleXStart);
		temppart->SetScaleYStart(m_fScaleYStart);
		temppart->SetScaleXEnd(m_fScaleXEnd);
		temppart->SetScaleYEnd(m_fScaleYEnd);
		//setting blend modes
		temppart->SetSourceBlend(m_eSourceBlend);
		temppart->SetDestBlend(m_eDestBlend);
		temppart->SetImageID(m_nImageID);
		temppart->SetCurrLife(0);
		m_lLive.push_back(temppart);
	}
}
bool CParticleEmitter::Load(const char* strName)
{
	TiXmlDocument doc;
	if(doc.LoadFile(strName) == false)
		return false;
	TiXmlElement* pRoot = doc.RootElement();
	if(pRoot == nullptr)
		return false;
	TiXmlElement* pSpawnRect = pRoot->FirstChildElement("SpawnRect");
	while (pSpawnRect != nullptr)
	{
		double RectL = 0;
		pSpawnRect->Attribute("RenderLeft", &RectL);
		m_rSpawnRect.left = (LONG)RectL;

		RectL = 0;
		pSpawnRect->Attribute("RenderTop", &RectL);
		m_rSpawnRect.top = (LONG)RectL;

		RectL = 0;
		pSpawnRect->Attribute("RenderRight", &RectL);
		m_rSpawnRect.right = (LONG)RectL;

		RectL = 0;
		pSpawnRect->Attribute("RenderBottom", &RectL);
		m_rSpawnRect.bottom = (LONG)RectL;
		pSpawnRect = pSpawnRect->NextSiblingElement("SpawnRect");
	}
	TiXmlElement* pImageData = pRoot->FirstChildElement("ImageData");
	while(pImageData != nullptr)
	{
		double IMDA = 0;
		pImageData->Attribute("Height", &IMDA);
		m_fHeight = (float)IMDA;

		IMDA = 0;
		pImageData->Attribute("Width", &IMDA);
		m_fWidth = (float)IMDA;

		IMDA = 0;
		pImageData->Attribute("PosX", &IMDA);
		m_nPosX = (int)IMDA;

		IMDA = 0;
		pImageData->Attribute("PosY", &IMDA);
		m_nPosY = (int)IMDA;

		const char* pText = pImageData->Attribute("Path");
		TCHAR theText[1000];
		mbstowcs_s(nullptr, theText, pText,_TRUNCATE);
		m_nImageID = m_pTM->LoadTexture(theText, 0);
		pImageData = pImageData->NextSiblingElement("ImageData");
	}
	TiXmlElement* pEmitterVariables = pRoot->FirstChildElement("EmitterVariables");
	while(pEmitterVariables != nullptr)
	{
		double EMVA = 0;
		pEmitterVariables->Attribute("MaxParticles", &EMVA);
		m_nMaxParticle = (int)EMVA;

		EMVA = 0;
		pEmitterVariables->Attribute("LifeMin", &EMVA);
		m_fLifeMin = (float)EMVA;

		EMVA = 0;
		pEmitterVariables->Attribute("LifeMax", &EMVA);
		m_fLifeMax = (float)EMVA;

		int thebool = 0;
		pEmitterVariables->Attribute("Looping", &thebool);
		if(thebool == 0)
			m_bLooping = false;
		else
			m_bLooping = true;

		EMVA = 0;
		pEmitterVariables->Attribute("SpawnRate", &EMVA);
		m_fSpawnRate = (float)EMVA;

		int temp = 0;
		pEmitterVariables->Attribute("DestBlend", &temp);
		if(temp > 15)
			temp = 15;
		m_eDestBlend = (D3DRENDERSTATETYPE)temp;

		temp = 0;
		pEmitterVariables->Attribute("SourceBlend", &temp);
		if(temp > 15)
		temp = 15;
		m_eSourceBlend = (D3DRENDERSTATETYPE)temp;
		pEmitterVariables = pEmitterVariables->NextSiblingElement("EmitterVariables");
	}
	TiXmlElement* pMovement = pRoot->FirstChildElement("Movement");
	while(pMovement != nullptr)
	{
		double MOVE = 0;
		pMovement->Attribute("RotationStart", &MOVE);
		m_fRotationStart = (float)MOVE;
		m_fRotationStart = static_cast<float>(MOVE);

		MOVE = 0;
		pMovement->Attribute("RotationEnd", &MOVE);
		m_fRotationEnd = (float)MOVE;

		MOVE = 0;
		pMovement->Attribute("VelXStart", &MOVE);
		m_fVelocityXStart = (int)MOVE;

		MOVE = 0;
		pMovement->Attribute("VelXMin", &MOVE);
		m_fVelocityXMin = (int)MOVE;

		MOVE = 0;
		pMovement->Attribute("VelXEnd", &MOVE);
		m_fVelocityXEnd = (int)MOVE;

		MOVE = 0;
		pMovement->Attribute("VelXMax", &MOVE);
		m_fVelocityXMax = (int)MOVE;

		MOVE = 0;
		pMovement->Attribute("VelYStart", &MOVE);
		m_fVelocityYStart = (int)MOVE;

		MOVE = 0;
		pMovement->Attribute("VelYMin", &MOVE);
		m_fVelocityYMin = (int)MOVE;

		MOVE = 0;
		pMovement->Attribute("VelYEnd", &MOVE);
		m_fVelocityYEnd = (int)MOVE;

		MOVE = 0;
		pMovement->Attribute("VelYMax", &MOVE);
		m_fVelocityYMax = (int)MOVE;

		MOVE = 0;
		pMovement->Attribute("ScaleXStart", &MOVE);
		m_fScaleXStart = (float)MOVE;

		MOVE = 0;
		pMovement->Attribute("ScaleXEnd", &MOVE);
		m_fScaleXEnd = (float)MOVE;

		MOVE = 0;
		pMovement->Attribute("ScaleYStart", &MOVE);
		m_fScaleYStart = (float)MOVE;

		MOVE = 0;
		pMovement->Attribute("ScaleYEnd", &MOVE);
		m_fScaleYEnd = (float)MOVE;
		pMovement = pMovement->NextSiblingElement("Movement");
	}
	TiXmlElement* pColorData = pRoot->FirstChildElement("ColorData");
	while(pColorData != nullptr)
	{
		double CODA = 0;
		pColorData->Attribute("RStart", &CODA);
		m_nColorRStart = (int)CODA;

		CODA = 0;
		pColorData->Attribute("REnd", &CODA);
		m_nColorREnd = (int)CODA;

		CODA = 0;
		pColorData->Attribute("GStart", &CODA);
		m_nColorGStart = (int)CODA;

		CODA = 0;
		pColorData->Attribute("GEnd", &CODA);
		m_nColorGEnd = (int)CODA;

		CODA = 0;
		pColorData->Attribute("BStart", &CODA);
		m_nColorBStart = (int)CODA;

		CODA = 0;
		pColorData->Attribute("BEnd", &CODA);
		m_nColorBEnd = (int)CODA;

		CODA = 0;
		pColorData->Attribute("AStart", &CODA);
		m_nColorAStart = (int)CODA;

		CODA = 0;
		pColorData->Attribute("AEnd", &CODA);
		m_nColorAEnd = (int)CODA;
		pColorData = pColorData->NextSiblingElement("ColorData");
	}
	return true;
}